{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "dad872cf-ff98-435d-a91a-b28a88354ee1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test set size: 10000\n",
      "Training set size: 60000\n",
      "Number of training samples: 48780\n",
      "Number of cross-validation samples: 5430\n"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "import torchvision\n",
    "import torchvision.transforms as transforms\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "label_size = 18 # Label size\n",
    "ticklabel_size = 14 # Tick label size\n",
    "    \n",
    "# Define a transform to normalize the data\n",
    "transform = transforms.Compose([\n",
    "    transforms.ToTensor()\n",
    "])\n",
    "\n",
    "# Load test data from the MNIST\n",
    "testset = torchvision.datasets.MNIST(root='./Data', train=False, download=False, transform=transform)\n",
    "print(f\"Test set size: {len(testset)}\")\n",
    "\n",
    "# Load training data from the MNIST\n",
    "trainset = torchvision.datasets.MNIST(root='./Data', train=True, download=False, transform=transform)\n",
    "print(f\"Training set size: {len(trainset)}\")\n",
    "\n",
    "# Rate of trX and cvX\n",
    "tr_cv_rate = 0.9\n",
    "\n",
    "# Create a list to store indices for each class unique()\n",
    "class_indices = [[] for _ in range(10)]  # 10 classes in MNIST\n",
    "\n",
    "# Populate class_indices\n",
    "for idx, (_, label) in enumerate(trainset):\n",
    "    class_indices[label].append(idx)\n",
    "\n",
    "# Calculate the number of samples for each class in training and validation sets\n",
    "train_size_per_class = int(tr_cv_rate * min(len(indices) for indices in class_indices))\n",
    "val_size_per_class = min(len(indices) for indices in class_indices) - train_size_per_class\n",
    "\n",
    "# Create balanced train and validation sets\n",
    "train_indices = []\n",
    "val_indices = []\n",
    "for indices in class_indices:\n",
    "    train_indices.extend(indices[:train_size_per_class])\n",
    "    val_indices.extend(indices[train_size_per_class:train_size_per_class + val_size_per_class])\n",
    "\n",
    "# Create Subset datasets\n",
    "from torch.utils.data import Subset\n",
    "trX = Subset(trainset, train_indices)\n",
    "cvX = Subset(trainset, val_indices)\n",
    "\n",
    "print(f\"Number of training samples: {len(trX)}\")\n",
    "print(f\"Number of cross-validation samples: {len(cvX)}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "6c5096ab-9e50-4a64-86e5-1d0c712fa941",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "image_channels is 1\n",
      "tensor([[0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],\n",
      "        [1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],\n",
      "        [0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],\n",
      "        [1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],\n",
      "        [1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],\n",
      "        [1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 1.],\n",
      "        [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],\n",
      "        [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],\n",
      "        [0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 1., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 1.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 1.],\n",
      "        [0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 1., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 1.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],\n",
      "        [1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 1., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],\n",
      "        [0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],\n",
      "        [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],\n",
      "        [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.]])\n"
     ]
    }
   ],
   "source": [
    "batch_size = 42 # Define training batch 1，\n",
    "\n",
    "def one_hot_collate(batch):\n",
    "    data = torch.stack([item[0] for item in batch])\n",
    "    labels = torch.tensor([item[1] for item in batch])\n",
    "    one_hot_labels = torch.zeros(labels.size(0), 10)  # 10 classes in MNIST 【0，1，0，0】\n",
    "    one_hot_labels.scatter_(1, labels.unsqueeze(1), 1)\n",
    "    return data, one_hot_labels\n",
    "\n",
    "trLoader = torch.utils.data.DataLoader(trX, batch_size=batch_size, shuffle=True, num_workers=0, collate_fn=one_hot_collate)\n",
    "cvLoader = torch.utils.data.DataLoader(cvX, batch_size=batch_size, shuffle=False, num_workers=0, collate_fn=one_hot_collate)\n",
    "teLoader = torch.utils.data.DataLoader(testset, batch_size=batch_size, shuffle=False, num_workers=0, collate_fn=one_hot_collate)\n",
    "\n",
    "# Get a batch of training data\n",
    "dataiter = iter(trLoader)\n",
    "data, labels = next(dataiter)\n",
    "\n",
    "image_channels = data[0].numpy().shape[0]\n",
    "print(f'image_channels is {image_channels}')\n",
    "print(labels)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "a6687003-07a5-4b92-94e2-3a319b56cb63",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CNN(\n",
      "  (conv1): Conv2d(1, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
      "  (pool1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)\n",
      "  (conv2): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
      "  (pool2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)\n",
      "  (fc1): Linear(in_features=3136, out_features=100, bias=True)\n",
      "  (fc2): Linear(in_features=100, out_features=10, bias=True)\n",
      "  (softmax): Softmax(dim=1)\n",
      ")\n"
     ]
    }
   ],
   "source": [
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "import torch.optim as optim\n",
    "\n",
    "class CNN(nn.Module):\n",
    "    def __init__(self, image_channels, num_classes):\n",
    "        super(CNN, self).__init__()\n",
    "        \n",
    "        # First convolutional layer\n",
    "        self.conv1 = nn.Conv2d(in_channels=image_channels, out_channels=32, kernel_size=3, padding=1)\n",
    "        self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)\n",
    "        \n",
    "        # Second convolutional layer\n",
    "        self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)\n",
    "        self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)\n",
    "        \n",
    "        # Fully connected layers\n",
    "        self.fc1 = nn.Linear(64 * 7 * 7, 100)  # After two 2x2 max pools, 28x28 -> 7x7\n",
    "        self.fc2 = nn.Linear(100, num_classes)  # 10 classes output\n",
    "\n",
    "        # Softmax\n",
    "        self.softmax = nn.Softmax(dim=1)\n",
    "        \n",
    "    def forward(self, x):\n",
    "        # Remove the reshape operation and directly use x\n",
    "        x = F.relu(self.conv1(x))\n",
    "        x = self.pool1(x)\n",
    "        \n",
    "        # Second conv layer\n",
    "        x = F.relu(self.conv2(x))\n",
    "        x = self.pool2(x)\n",
    "        \n",
    "        # Flatten the output for the fully connected layers\n",
    "        x = x.view(-1, 64 * 7 * 7)\n",
    "        \n",
    "        # Fully connected layers\n",
    "        x = F.relu(self.fc1(x))\n",
    "        x = self.fc2(x)\n",
    "        \n",
    "        # Softmax\n",
    "        x = self.softmax(x)\n",
    "        \n",
    "        return x\n",
    "\n",
    "# Initialize the model\n",
    "model = CNN(image_channels, 10)\n",
    "if torch.cuda.is_available():\n",
    "    model = model.cuda()\n",
    "\n",
    "# Display model architecture\n",
    "print(model)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "46f0f72c-8cbc-4bb2-95ac-9f4cccb4b582",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch [1/10], Train Loss: 1.6458, CV Loss: 1.5886\n",
      "Epoch [2/10], Train Loss: 1.5422, CV Loss: 1.4858\n",
      "Epoch [3/10], Train Loss: 1.4822, CV Loss: 1.4833\n",
      "Epoch [4/10], Train Loss: 1.4781, CV Loss: 1.4887\n",
      "Epoch [5/10], Train Loss: 1.4748, CV Loss: 1.4835\n",
      "Epoch [6/10], Train Loss: 1.4725, CV Loss: 1.4802\n",
      "Epoch [7/10], Train Loss: 1.4726, CV Loss: 1.4763\n",
      "Epoch [8/10], Train Loss: 1.4710, CV Loss: 1.4781\n",
      "Epoch [9/10], Train Loss: 1.4707, CV Loss: 1.4789\n",
      "Epoch [10/10], Train Loss: 1.4704, CV Loss: 1.4743\n"
     ]
    }
   ],
   "source": [
    "# Define loss function and optimizer\n",
    "criterion = nn.CrossEntropyLoss() # Loss\n",
    "optimizer = torch.optim.Adam(model.parameters()) # Adam\n",
    "\n",
    "# Lists to store losses\n",
    "train_losses = []\n",
    "cv_losses = []\n",
    "\n",
    "# Number of epochs\n",
    "num_epochs = 10\n",
    "\n",
    "for epoch in range(num_epochs):\n",
    "    model.train()\n",
    "    batch_losses = []\n",
    "    \n",
    "    for batch_x, batch_y in trLoader:\n",
    "        # Forward pass\n",
    "        outputs = model(batch_x)\n",
    "        loss = criterion(outputs, batch_y)\n",
    "        \n",
    "        # Backward pass and optimize\n",
    "        optimizer.zero_grad()\n",
    "        loss.backward()\n",
    "        optimizer.step()\n",
    "        \n",
    "        batch_losses.append(loss.item())\n",
    "    \n",
    "    # Calculate average training loss for this epoch\n",
    "    avg_train_loss = sum(batch_losses) / len(batch_losses)\n",
    "    train_losses.append(avg_train_loss)\n",
    "    \n",
    "    # Evaluate on cross-validation set\n",
    "    model.eval()\n",
    "    cv_batch_losses = []\n",
    "    with torch.no_grad():\n",
    "        for cv_x, cv_y in cvLoader:\n",
    "            cv_outputs = model(cv_x)\n",
    "            cv_loss = criterion(cv_outputs, cv_y)\n",
    "            cv_batch_losses.append(cv_loss.item())\n",
    "    \n",
    "    avg_cv_loss = sum(cv_batch_losses) / len(cv_batch_losses)\n",
    "    cv_losses.append(avg_cv_loss)\n",
    "    \n",
    "    print(f'Epoch [{epoch+1}/{num_epochs}], Train Loss: {avg_train_loss:.4f}, CV Loss: {avg_cv_loss:.4f}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "b0772b13-81fb-4b51-ad43-635030c4d59c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy on training set: 99.39%\n",
      "Accuracy on cross-validation set: 98.67%\n"
     ]
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 1000x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import torch\n",
    "import matplotlib.pyplot as plt\n",
    "import os\n",
    "os.environ['KMP_DUPLICATE_LIB_OK']='True'\n",
    "# 确保以下变量已经定义并初始化\n",
    "# model, trLoader, cvLoader, train_losses, cv_losses, num_epochs\n",
    "\n",
    "try:\n",
    "    model.eval()\n",
    "    with torch.no_grad():\n",
    "        # Training set accuracy\n",
    "        tr_correct = 1\n",
    "        tr_total = 1\n",
    "        for images, labels in trLoader:\n",
    "            outputs = model(images)\n",
    "            _, predicted = torch.max(outputs, 1)\n",
    "            _, true_labels = torch.max(labels, 1)\n",
    "            tr_total += labels.size(0)\n",
    "            tr_correct += (predicted == true_labels).sum().item()\n",
    "        \n",
    "        tr_accuracy = 100 * tr_correct / tr_total\n",
    "        \n",
    "        # Test set accuracy\n",
    "        cv_correct = 0\n",
    "        cv_total = 0\n",
    "        for images, labels in cvLoader:\n",
    "            outputs = model(images)\n",
    "            _, predicted = torch.max(outputs, 1)\n",
    "            _, true_labels = torch.max(labels, 1)\n",
    "            cv_total += labels.size(0)\n",
    "            cv_correct += (predicted == true_labels).sum().item()\n",
    "        \n",
    "        cv_accuracy = 100 * cv_correct / cv_total\n",
    "\n",
    "    print(f'Accuracy on training set: {tr_accuracy:.2f}%')\n",
    "    print(f'Accuracy on cross-validation set: {cv_accuracy:.2f}%')\n",
    "\n",
    "    # Plot training and cross-validation losses\n",
    "    plt.figure(figsize=(10, 5))\n",
    "    plt.plot(range(1, num_epochs+1), train_losses, label='Training Loss')\n",
    "    plt.plot(range(1, num_epochs+1), cv_losses, label='Cross-Validation Loss')\n",
    "    plt.xlabel('Epoch')\n",
    "    plt.ylabel('Loss')\n",
    "    plt.title('Training and Cross-Validation Loss')\n",
    "    plt.legend()\n",
    "    plt.show()\n",
    "\n",
    "except Exception as e:\n",
    "    print(f\"An error occurred: {e}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4a02f5c7-2bc9-4168-a68f-e36335549364",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
